
<template>
  <div 
  ref="terminalRef" 
  class="terminal" 
  :class="{ 'fullscreen': isFullscreen }"
  @wheel.stop 
  >
  </div>
</template>
 
<script setup>
import { Terminal } from '@xterm/xterm';
import '@xterm/xterm/css/xterm.css';
import { FitAddon } from '@xterm/addon-fit';
import { useEventListener } from '@vueuse/core';
const CHAR_WIDTH = 20;
const CHAR_HEIGHT = 19;
const TERMINAL_CONFIG = {
  disableStdin: false,
  fontSize: 16,
  fontFamily: 'Consolas, "Courier New", monospace',
  fontWeight: 'normal',
  fontWeightBold: 'bold',
  letterSpacing: 0,
  lineHeight: 1.0,
  scrollback: 1000,
  scrollSensitivity: 1,
  fastScrollModifier: 'Shift',
  fastScrollSensitivity: 5,
  logLevel: 'info',
  allowTransparency: true,
  theme: {
    cursor: '#ffffff',
    cursorAccent: '#000000', 
    foreground: '#ffffff',
    background: '#1e1e1e',
    selection: '#ffffff40',
  },
  convertEol: true,
  cursorBlink: true,
  cursorStyle: 'block',
  cursorWidth: 1,
  altClickMovesCursor: true,
  rightClickSelectsWord: true,
  windowsMode: true,
};
const isFullscreen = defineModel('isFullscreen', {
  type: Boolean,
  required: false,
  default: false
});
const terminalRef = ref(null);
const terminal = new Terminal(TERMINAL_CONFIG);
const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon);
let inputBuffer = '';
let dataListener = null;
function listenUdpMessage() {
  window.electron.onUdpMessage((data) => {
    try {
      console.log(data, "返回udp消息");      
      const messageObj = JSON.parse(data.message);
      let result = messageObj.result || " ";  
      const prompt = messageObj.prompt || " ";  
      if (result !== " ") {
      console.log(result,"result");  
      result = result
          .replace(/\n/g, ' ') 
          .split(/\s+/) 
          .filter(Boolean) 
          .join('  '); 
      }    
      terminal.write(prompt);
      terminal.write(result);
      if(result !== ' '){
        terminal.write('\r\n');
        window.electron.sendMessageToMain({
          commands:'JRLC.UDP.INPUT',
          message:''
        })
      }
    } catch (error) {
      console.error('解析 UDP 消息失败:', error);
    }
  });
}
function handleTerminalData(data) {
  switch (data) {
    case '\r': 
      if (inputBuffer.trim()) {
        window.electron.sendMessageToMain({
          commands:'JRLC.UDP.INPUT',
          message:inputBuffer.trim()
        });
        terminal.write('\r\n');
      }else{
        terminal.write('\r\n');
        window.electron.sendMessageToMain({
          commands:'JRLC.UDP.INPUT',
          message:''
        });
      }
      inputBuffer = '';
      break;
    case '\u007F': 
      if (inputBuffer.length > 0) {
        inputBuffer = inputBuffer.slice(0, -1);
        terminal.write('\b \b');
      }
      break;
    case 'clear': 
      terminal.clear();
      break;
    default: 
      inputBuffer += data;
      terminal.write(data);
      break;
  }
}
const handleEscape = (event) => {
  if (event.key === 'Escape' && isFullscreen.value) {
    isFullscreen.value = false;
    nextTick(() => terminal.scrollToBottom());
  }
};
function resizeTerminal() {
  if (!terminal || !fitAddon || !terminalRef.value) return;
  fitAddon.fit();
  const { offsetWidth: containerWidth, offsetHeight: containerHeight } = terminalRef.value;
  const cols = Math.floor(containerWidth / CHAR_WIDTH);
  const rows = Math.floor(containerHeight / CHAR_HEIGHT);
  terminal.resize(cols, rows);
  setTimeout(() => {
    fitAddon.fit();
    terminal.scrollToBottom();
  }, 0);
}


onMounted(() => {
  terminal.open(terminalRef.value);
  const terminalElement = terminalRef.value;
  terminalElement.addEventListener('wheel', (e) => {l
    e.stopPropagation();
    e.preventDefault();
  }, { passive: false });
  terminal.onKey(({ domEvent }) => {
    if (domEvent.key === 'Escape' && isFullscreen.value) {
      isFullscreen.value = false;
      setTimeout(resizeTerminal, 300);
      domEvent.preventDefault();
    }
    if (domEvent.ctrlKey && domEvent.key === 'c') {
      window.electron.sendMessageToMain({
        commands:'JRLC.UDP.INPUT',
        message:'\u0003'
      })
    }
  });
  document.addEventListener('keydown', handleEscape);
  terminal.onData(handleTerminalData)
  listenUdpMessage()
  nextTick(resizeTerminal);
});

function disconnectTerminal() {
  terminal.clear();
  if (dataListener) {
    terminal.off('data', dataListener);
    dataListener = null;
  }
}

function toggleFullscreen() {
  isFullscreen.value = !isFullscreen.value;
  setTimeout(resizeTerminal, 300);
}

useEventListener(window, 'beforeunload', (event) => {
  disconnectTerminal();
  terminal?.dispose();
  event.preventDefault();
  event.returnValue = '';
});
defineExpose({
  disconnectTerminal,
  resizeTerminal,
  toggleFullscreen
});
</script>
 
<style scoped lang="scss">
.terminal {
  width: 100%;
  height: 40%;
  overflow: hidden;
  transition: all 0.3s ease;
  &.fullscreen {
    position: fixed;
    top: 0;
    left: 0;
    right: 0; 
    bottom: 0; 
    width: 100vw ;
    height: 100vh;
    margin: 0;
    padding: 0;
    z-index: 9999; // 提高层级
    background: #1e1e1e;
    & > * {
      margin: 0 ;
      padding: 0 ;
    }
  }
  :deep(.xterm) {
    height: 100%;
    .xterm-screen {
      position: relative;
    }
    .xterm-viewport {
      position: absolute;
      overflow-y: scroll; 
      width: 100% !important; 
      height: 100% !important;
      &:hover {
        isolation: isolate;  
      }
    }
  }
}
.terminal ::-webkit-scrollbar {
  width: 8PX; 
  height: 8PX; 
}

.terminal ::-webkit-scrollbar-thumb {
  background-color: #f1f1f1; /* 滚动条颜色，亮蓝色 */
  border-radius: 4px; /* 滚动条圆角 */
}

.terminal ::-webkit-scrollbar-thumb:hover {
  background-color: #125ea1; /* 悬停时滚动条颜色，加深的蓝色 */
}

.terminal ::-webkit-scrollbar-track {
  background: #1976D2; /* 滚动条背景颜色，浅灰色 */
}
</style>

